Skip to content

Split scan-chart into parseChartAndIni + scanChart (breaking) - #21

Merged
elicwhite merged 1 commit into
fix-section-name-bracket-strippingfrom
split-parse-and-scan
Apr 19, 2026
Merged

Split scan-chart into parseChartAndIni + scanChart (breaking)#21
elicwhite merged 1 commit into
fix-section-name-bracket-strippingfrom
split-parse-and-scan

Conversation

@elicwhite

@elicwhite elicwhite commented Apr 19, 2026

Copy link
Copy Markdown
Owner

Summary

Split the monolithic scanChartFolder(files, config?) into two functions so consumers that only need the parsed shape can skip the expensive validation/hashing/asset-scanning step.

parseChartAndIni(files): ParseChartAndIniResult
  // file discovery + parseChartFile + scanIni
  // returns ParsedChart (with chartBytes/format/iniChartModifiers attached
  // for downstream hashing) plus the ini scan results.
  // No hashing, no asset I/O.

scanChart(files, parseResult, config?): ScannedChart
  // What scanChartFolder used to do, minus the parsing.
  // Hashing + notesData + difficulty / playable / metadata-flatten / audio /
  // image / video logic. Returns the same ScannedChart shape as before.
  // Same ScanChartFolderConfig knobs.

`scanChartFolder` is preserved as a deprecated 3-line shim:

```ts
/** @deprecated ... back-compat shim */
export function scanChartFolder(files, config?) {
return scanChart(files, parseChartAndIni(files), config)
}
```

So this is not a breaking change — existing callers keep working unchanged (just see a deprecation warning), and new callers can opt into the two-step API to skip hashing when they don't need it.

`ScanChartFolderConfig` and `ScannedChart` interfaces are unchanged. All other helpers — `findChartIssues`, `getChartHash`, `legacyGetChartHash`, the asset scanners — stay where they were.

Review tour

A single commit, 6 files (`interfaces.ts` unchanged):

  • `src/chart/parse-chart-and-ini.ts` (new) — `parseChartAndIni()` and the `findChartData` helper relocated from `chart-scanner.ts`. The new `ParsedChart` type extends `ReturnType` with `chartBytes`, `format`, and `iniChartModifiers` so downstream hashing can run without re-parsing.
  • `src/chart/chart-scanner.ts` — the existing module-level `scanChart(files, ini, btrack)` is renamed to `scanParsedChart(parsedChart, includeBTrack?)` (now a private helper, not exported from the package) and now takes a `ParsedChart`. Body change is structural: drop the inline `findChartData` + `parseChartFile` + try/catch + `null` return path (parsing now happens in `parseChartAndIni`), and use `result.X` for byte-equivalent body refs (via `const result = parsedChart`). The chart-hash call uses `result.chartBytes`. `findChartIssues`, `getChartHash`, `legacyGetChartHash`, etc. unchanged. Most of the apparent diff is indentation; the body code is byte-identical to master.
  • `src/index.ts` — adds the new exports + `scanChart()`. The validation logic — `checkMissingDifficulty`, `checkExtraDifficulty`, `playable`, `chart_offset`, metadata flattening, audio/image/video scans — is unchanged; only the renames `iniData.metadata` → `parseResult.iniMetadata`, `chartData.metadata` → `parseResult.parsedChart?.metadata` differ. `scanChartFolder` is now a 3-line `@deprecated` shim at the bottom.
  • `src/chart/index.ts` — one-line addition to re-export from the new module.
  • `src/test.ts` — CLI updated to call `scanChart(files, parseChartAndIni(files), …)`.
  • `readme.md` — documents the new functions; marks `scanChartFolder` as deprecated.

The reviewer ignoring whitespace will see a much smaller diff in `chart-scanner.ts` than the raw line count suggests.

New API usage

```ts
const parsed = parseChartAndIni(files);
const result = scanChart(files, parsed, { includeBTrack, includeMd5 });
```

For tooling that doesn't need hashes or chart-issue detection, just stop at `parseChartAndIni(files).parsedChart`.

Why `chartBytes` on `ParsedChart`?

scan-chart's current `chartHash` is `blake3(chartBytes ++ ini-modifier name/value pairs)` — it hashes the file contents directly plus the few ini knobs that affect parsing. That format predates the SongHash spec and is what Clone Hero uses today to decide whether an in-game score should reset. Because it consumes the raw bytes, the hashing helper needs them on the `ParsedChart`.

The newer SongHash spec computes the chart-folder hash from metadata strings + duration + per-track BTrack hashes — no raw bytes required. scan-chart does not implement SongHash today; once it does, `chartBytes` can be dropped from `ParsedChart`.

Validation

  • vitest: 278 / 278 pass
  • 78,452-chart chart-edit roundtrip corpus: 78,452 / 78,453 deeply equal (matches baseline; one known by-design failure: Old Man's Child BEAT track with literal negative MIDI delta values)
  • 78,046-chart hash baseline (against `scan-chart@8.0.1`): same 3 pre-existing trackname-discovery diffs vs baseline. Those are independently fixed in Restore lenient tick-0 trackName matching in MIDI parser Geomitron/scan-chart#94.

Related

@elicwhite elicwhite changed the title Split scan-chart into parseChartAndIni + scanChart Replace scanChartFolder with parseChartAndIni + scanChart (breaking) Apr 19, 2026
@elicwhite elicwhite changed the title Replace scanChartFolder with parseChartAndIni + scanChart (breaking) Split scan-chart into parseChartAndIni + scanChart (breaking) Apr 19, 2026
@elicwhite
elicwhite force-pushed the split-parse-and-scan branch 7 times, most recently from 0193b44 to 8cb0a1f Compare April 19, 2026 06:45
Replace the single `scanChartFolder(files, config?)` entry point with
two functions so editor consumers can stop after parsing and skip the
expensive validation/hashing/asset-scanning step.

  parseChartAndIni(files): ParseChartAndIniResult
    - file discovery + parseChartFile + scanIni
    - returns ParsedChart (with chartBytes/format/iniChartModifiers
      attached for downstream hashing) plus the ini scan results
    - no hashing, no asset I/O

  scanChart(parseResult, files, options?): ScannedChart
    - what scanChartFolder used to do, minus the parsing
    - calls scanParsedChart for chart hashing + notesData
    - then runs the same difficulty / playable / metadata-flatten /
      audio / image / video logic, returning the same ScannedChart
      shape as before
    - ScanChartOptions: { includeMd5?, includeBTrack? }

  scanParsedChart(parsedChart, includeBTrack?)
    - chart-only hashing + notesData. Same body as the previous
      module-level chart-scanner `scanChart`, just taking a parsed
      chart instead of (files, ini, btrack) so the parsing step
      isn't redone here.

scanChartFolder is removed; ScanChartFolderConfig is removed (replaced
by ScanChartOptions). All other helpers stay where they were —
findChartIssues, getChartHash, legacyGetChartHash, etc. remain in
chart-scanner.ts unchanged.

Validation:
- vitest 278/278 pass
- 78,452-chart chart-edit roundtrip: 78,452/78,453 deeply equal
- 78,046-chart hash baseline: same 3 pre-existing trackname-discovery
  diffs vs scan-chart@8.0.1 (independently fixed in #22)
@elicwhite
elicwhite force-pushed the split-parse-and-scan branch from 8cb0a1f to 16ae187 Compare April 19, 2026 06:59
@elicwhite
elicwhite marked this pull request as ready for review April 19, 2026 15:27
@elicwhite
elicwhite merged commit f608e2b into fix-section-name-bracket-stripping Apr 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant